package top.ywlog.permission.service;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import top.ywlog.permission.dao.SysAclMapper;
import top.ywlog.permission.dao.SysAclModuleMapper;
import top.ywlog.permission.dao.SysDeptMapper;
import top.ywlog.permission.dto.AclDto;
import top.ywlog.permission.dto.AclModuleLevelDto;
import top.ywlog.permission.dto.DeptLevelDto;
import top.ywlog.permission.model.SysAcl;
import top.ywlog.permission.model.SysAclModule;
import top.ywlog.permission.model.SysDept;
import top.ywlog.permission.util.LevelUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author: Durian
 * @date: 2020/10/19 20:30
 * @description:
 */
@Service
public class SysTreeService
{
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private SysAclModuleMapper sysAclModuleMapper;
    @Resource
    private SysAclMapper sysAclMapper;
    @Resource
    private SysCoreService sysCoreService;

    /**
     * 部门树
     *
     * @return 部门树结构数据
     */
    public List<DeptLevelDto> deptTree()
    {
        List<SysDept> deptList = sysDeptMapper.getAllDept();

        List<DeptLevelDto> dtoList = Lists.newArrayList();
        for (SysDept dept : deptList)
        {
            DeptLevelDto dto = DeptLevelDto.getInstance(dept);
            dtoList.add(dto);
        }
        return deptListToTree(dtoList);
    }

    /**
     * 权限模块数
     *
     * @return 权限模块树机构数据
     */
    public List<AclModuleLevelDto> aclModuleTree()
    {
        List<SysAclModule> aclModuleList = sysAclModuleMapper.getAllAclModule();
        List<AclModuleLevelDto> dtoList = Lists.newArrayList();
        for (SysAclModule aclModule : aclModuleList)
        {
            dtoList.add(AclModuleLevelDto.getInstance(aclModule));
        }
        return aclModuleListToTree(dtoList);
    }

    public List<AclModuleLevelDto> roleTree(int roleId)
    {
        // 1、当前用户已分配的权限点
        List<SysAcl> userAclList = sysCoreService.getCurrentUserAclList();
        // 2、当前角色分配的权限点
        List<SysAcl> roleAclList = sysCoreService.getRoleAclList(roleId);
        // 3、当前系统所有权限点
        List<AclDto> aclDtoList = Lists.newArrayList();

        Set<Integer> userAclIdSet = userAclList.stream().map(SysAcl::getId).collect(Collectors.toSet());
        Set<Integer> roleAclIdSet = roleAclList.stream().map(SysAcl::getId).collect(Collectors.toSet());

        List<SysAcl> allAclList = sysAclMapper.getAll();
        for (SysAcl acl : allAclList)
        {
            AclDto dto = AclDto.adapt(acl);
            if (userAclIdSet.contains(acl.getId()))
            {
                dto.setHasAcl(true);
            }
            if (roleAclIdSet.contains(acl.getId()))
            {
                dto.setChecked(true);
            }
            aclDtoList.add(dto);
        }
        return aclListToTree(aclDtoList);
    }

    private List<AclModuleLevelDto> aclListToTree(List<AclDto> aclDtoList)
    {
        if (CollectionUtils.isEmpty(aclDtoList))
        {
            return Lists.newArrayList();
        }
        List<AclModuleLevelDto> aclModuleLevelList = aclModuleTree();

        Multimap<Integer, AclDto> moduleIdAclMap = ArrayListMultimap.create();
        for (AclDto acl : aclDtoList)
        {
            if (acl.getStatus() == 1)
            {
                moduleIdAclMap.put(acl.getAclModuleId(), acl);
            }
        }
        bindAclWithOrder(aclModuleLevelList, moduleIdAclMap);
        return aclModuleLevelList;
    }

    private void bindAclWithOrder(List<AclModuleLevelDto> aclModuleLevelList, Multimap<Integer, AclDto> moduleIdAclMap)
    {
        if (CollectionUtils.isEmpty(aclModuleLevelList))
        {
            return;
        }
        for (AclModuleLevelDto dto : aclModuleLevelList)
        {
            List<AclDto> aclDtoList = (List<AclDto>) moduleIdAclMap.get(dto.getId());
            if (CollectionUtils.isNotEmpty(aclDtoList))
            {
                aclDtoList.sort(aclSeqComparator);
                dto.setAclList(aclDtoList);
            }
            bindAclWithOrder(dto.getAclModuleList(), moduleIdAclMap);
        }
    }

    private List<DeptLevelDto> deptListToTree(List<DeptLevelDto> deptLevelList)
    {
        if (CollectionUtils.isEmpty(deptLevelList))
        {
            return Lists.newArrayList();
        }
        // level -> [dept1, dept2, ...] Map<String, List<Object>>
        Multimap<String, DeptLevelDto> levelDeptMap = ArrayListMultimap.create();
        List<DeptLevelDto> rootList = Lists.newArrayList();

        for (DeptLevelDto dto : deptLevelList)
        {
            levelDeptMap.put(dto.getLevel(), dto);
            if (LevelUtils.ROOT.equals(dto.getLevel()))
            {
                rootList.add(dto);
            }
        }
        // 按照seq从小到大排序
        rootList.sort(Comparator.comparingInt(SysDept::getSeq));
        // 递归生成树
        transformDeptTree(rootList, LevelUtils.ROOT, levelDeptMap);
        return rootList;
    }


    private List<AclModuleLevelDto> aclModuleListToTree(List<AclModuleLevelDto> dtoList)
    {
        if (CollectionUtils.isEmpty(dtoList))
        {
            return Lists.newArrayList();
        }
        // level -> [aclmodule1, aclmodule2, ...] Map<String, List<Object>>
        Multimap<String, AclModuleLevelDto> levelAclModuleMap = ArrayListMultimap.create();
        List<AclModuleLevelDto> rootList = Lists.newArrayList();

        for (AclModuleLevelDto dto : dtoList)
        {
            levelAclModuleMap.put(dto.getLevel(), dto);
            if (LevelUtils.ROOT.equals(dto.getLevel()))
            {
                rootList.add(dto);
            }
        }
        rootList.sort(aclModuleSeqComparator);
        transformAclModuleTree(rootList, LevelUtils.ROOT, levelAclModuleMap);
        return rootList;
    }

    // level:0, 0, all 0->0.1,0.2
    // level:0.1
    // level:0.2
    private void transformDeptTree(List<DeptLevelDto> deptLevelList, String level, Multimap<String, DeptLevelDto> levelDeptMap)
    {
        for (DeptLevelDto deptLevelDto : deptLevelList)
        {
            // 遍历该层的每个元素
            // 处理当前层级的数据
            String nextLevel = LevelUtils.calculateLevel(level, deptLevelDto.getId());
            // 处理下一层
            List<DeptLevelDto> tempDeptList = (List<DeptLevelDto>) levelDeptMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempDeptList))
            {
                // 排序
                tempDeptList.sort(deptSeqComparator);
                // 设置下一层部门
                deptLevelDto.setDeptList(tempDeptList);
                // 进入到下一层处理
                transformDeptTree(tempDeptList, nextLevel, levelDeptMap);
            }
        }
    }

    private void transformAclModuleTree(List<AclModuleLevelDto> dtoList, String level, Multimap<String, AclModuleLevelDto> levelAclModuleMap)
    {
        for (AclModuleLevelDto dto : dtoList)
        {
            String nextLevel = LevelUtils.calculateLevel(level, dto.getId());
            List<AclModuleLevelDto> tempList = (List<AclModuleLevelDto>) levelAclModuleMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempList))
            {
                tempList.sort(aclModuleSeqComparator);
                dto.setAclModuleList(tempList);
                transformAclModuleTree(tempList, nextLevel, levelAclModuleMap);
            }
        }
    }


    private Comparator<DeptLevelDto> deptSeqComparator = Comparator.comparingInt(SysDept::getSeq);
    private Comparator<AclModuleLevelDto> aclModuleSeqComparator = Comparator.comparingInt(SysAclModule::getSeq);
    private Comparator<AclDto> aclSeqComparator = Comparator.comparingInt(SysAcl::getSeq);
}
